/**
 * Utils 模块 - 提供各种实用工具函数
 * 
 * @module Utils
 */

import fs from '@ohos.file.fs';
import crypto from '@ohos.security.crypto';

/**
 * ObjectId 类 - 生成和管理唯一标识符
 */
export class ObjectId {
  /**
   * 构造函数
   * @param {string} id - 可选的ObjectId字符串
   */
  constructor(id) {
    if (id) {
      if (!ObjectId.isValid(id)) {
        throw new Error('Invalid ObjectId');
      }
      this.id = id;
    } else {
      this.id = this.generate();
    }
  }
  
  /**
   * 生成新的ObjectId
   * @private
   * @returns {string} 生成的ObjectId字符串
   */
  generate() {
    // 获取时间戳的十六进制表示（4字节）
    const timestamp = Math.floor(Date.now() / 1000).toString(16).padStart(8, '0');
    
    // 生成随机部分（8字节）
    const randomPart = crypto.generateRandomNumbersSync(8).buffer;
    const randomHex = Array.from(new Uint8Array(randomPart))
      .map(b => b.toString(16).padStart(2, '0'))
      .join('');
    
    // 组合时间戳和随机部分
    return timestamp + randomHex;
  }
  
  /**
   * 检查字符串是否是有效的ObjectId
   * @static
   * @param {string} id - 要检查的字符串
   * @returns {boolean} 是否有效
   */
  static isValid(id) {
    return typeof id === 'string' && /^[0-9a-fA-F]{24}$/.test(id);
  }
  
  /**
   * 转换为字符串
   * @returns {string} ObjectId字符串
   */
  toString() {
    return this.id;
  }
  
  /**
   * 获取时间戳
   * @returns {number} 时间戳（秒）
   */
  getTimestamp() {
    return parseInt(this.id.substring(0, 8), 16);
  }
}

/**
 * Utils 模块的主要功能
 */
const Utils = {
  /**
   * 获取默认数据库路径
   * @param {string} dbName - 数据库名称
   * @returns {string} 数据库路径
   */
  getDefaultDatabasePath(dbName) {
    // 在鸿蒙系统中，应用数据应该存储在应用的沙盒目录中
    // 这里返回一个标准的路径格式
    return `data/storage/el2/base/${globalThis.abilityContext.applicationInfo.bundleName}/etsdb/${dbName}.db`;
  },
  
  /**
   * 初始化存储
   * @param {Config} config - 数据库配置
   * @returns {Promise<Object>} 存储对象
   */
  async initStorage(config) {
    if (config.inMemory) {
      // 初始化内存存储
      return this.initMemoryStorage();
    } else {
      // 初始化文件存储
      return await this.initFileStorage(config);
    }
  },
  
  /**
   * 初始化内存存储
   * @private
   * @returns {Object} 内存存储对象
   */
  initMemoryStorage() {
    const data = new Map();
    const listeners = new Map();
    
    return {
      // 保存文档
      saveDocument: async (collectionName, doc) => {
        if (!data.has(collectionName)) {
          data.set(collectionName, new Map());
        }
        
        const collection = data.get(collectionName);
        const id = doc._id || new ObjectId().toString();
        collection.set(id, { ...doc, _id: id });
        
        this._notifyListeners(listeners, collectionName, { type: 'save', doc });
      },
      
      // 查找文档
      findDocuments: async (collectionName, query) => {
        if (!data.has(collectionName)) {
          return [];
        }
        
        const collection = data.get(collectionName);
        const docs = Array.from(collection.values());
        
        // 简单的查询过滤（实际实现可能需要更复杂的查询解析）
        if (query) {
          return docs.filter(doc => this._matchesQuery(doc, query.query));
        }
        
        return docs;
      },
      
      // 根据ID查找文档
      findDocumentById: async (collectionName, id) => {
        if (!data.has(collectionName)) {
          return null;
        }
        
        const collection = data.get(collectionName);
        return collection.get(id) || null;
      },
      
      // 更新文档
      updateDocuments: async (collectionName, query, update) => {
        if (!data.has(collectionName)) {
          return 0;
        }
        
        const collection = data.get(collectionName);
        const docs = Array.from(collection.values());
        let updatedCount = 0;
        
        for (const doc of docs) {
          if (this._matchesQuery(doc, query)) {
            // 应用更新操作
            const updatedDoc = this._applyUpdate(doc, update);
            collection.set(doc._id, updatedDoc);
            updatedCount++;
            
            this._notifyListeners(listeners, collectionName, { type: 'update', doc: updatedDoc });
          }
        }
        
        return updatedCount;
      },
      
      // 删除文档
      deleteDocuments: async (collectionName, query) => {
        if (!data.has(collectionName)) {
          return 0;
        }
        
        const collection = data.get(collectionName);
        const docs = Array.from(collection.entries());
        let deletedCount = 0;
        
        for (const [id, doc] of docs) {
          if (this._matchesQuery(doc, query)) {
            collection.delete(id);
            deletedCount++;
            
            this._notifyListeners(listeners, collectionName, { type: 'delete', doc });
          }
        }
        
        return deletedCount;
      },
      
      // 开始事务
      beginTransaction: async () => {
        // 内存存储的事务相对简单，这里只是一个占位符
        console.log('ETSDB: Memory storage transaction began');
      },
      
      // 提交事务
      commitTransaction: async () => {
        console.log('ETSDB: Memory storage transaction committed');
      },
      
      // 回滚事务
      rollbackTransaction: async () => {
        console.log('ETSDB: Memory storage transaction rolled back');
      },
      
      // 监听集合变化
      watchCollection: (collectionName, callback) => {
        if (!listeners.has(collectionName)) {
          listeners.set(collectionName, []);
        }
        listeners.get(collectionName).push(callback);
      },
      
      // 取消监听
      unwatchCollection: (collectionName, callback) => {
        if (listeners.has(collectionName)) {
          const collectionListeners = listeners.get(collectionName);
          const index = collectionListeners.indexOf(callback);
          if (index !== -1) {
            collectionListeners.splice(index, 1);
          }
        }
      },
      
      // 获取统计信息
      getStats: async () => {
        let totalDocs = 0;
        let totalCollections = 0;
        
        data.forEach((collection, collectionName) => {
          totalCollections++;
          totalDocs += collection.size;
        });
        
        return {
          type: 'memory',
          collections: totalCollections,
          documents: totalDocs,
          size: 0 // 内存存储不计算大小
        };
      },
      
      // 关闭存储
      close: () => {
        // 内存存储关闭时不需要特殊操作
        console.log('ETSDB: Memory storage closed');
      }
    };
  },
  
  /**
   * 初始化文件存储
   * @private
   * @param {Config} config - 数据库配置
   * @returns {Promise<Object>} 文件存储对象
   */
  async initFileStorage(config) {
    try {
      // 确保目录存在
      const dbDir = config.path.substring(0, config.path.lastIndexOf('/'));
      await fs.mkdir(dbDir, 0o755, true);
      
      // 检查文件是否存在，不存在则创建
      try {
        await fs.access(config.path);
      } catch (error) {
        await fs.open(config.path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
      }
      
      console.log(`ETSDB: File storage initialized at ${config.path}`);
      
      // 返回文件存储接口（实际实现需要更复杂的文件操作）
      return {
        // 注意：这里的实现是简化版，实际的文件存储需要更复杂的逻辑
        saveDocument: async (collectionName, doc) => {
          // 文件存储的具体实现...
          console.log(`ETSDB: Saving document to ${collectionName}`);
        },
        
        findDocuments: async (collectionName, query) => {
          // 文件存储的具体实现...
          console.log(`ETSDB: Finding documents in ${collectionName}`);
          return [];
        },
        
        findDocumentById: async (collectionName, id) => {
          // 文件存储的具体实现...
          console.log(`ETSDB: Finding document by ID in ${collectionName}`);
          return null;
        },
        
        updateDocuments: async (collectionName, query, update) => {
          // 文件存储的具体实现...
          console.log(`ETSDB: Updating documents in ${collectionName}`);
          return 0;
        },
        
        deleteDocuments: async (collectionName, query) => {
          // 文件存储的具体实现...
          console.log(`ETSDB: Deleting documents in ${collectionName}`);
          return 0;
        },
        
        beginTransaction: async () => {
          console.log('ETSDB: File storage transaction began');
        },
        
        commitTransaction: async () => {
          console.log('ETSDB: File storage transaction committed');
        },
        
        rollbackTransaction: async () => {
          console.log('ETSDB: File storage transaction rolled back');
        },
        
        watchCollection: (collectionName, callback) => {
          console.log(`ETSDB: Watching collection ${collectionName}`);
        },
        
        unwatchCollection: (collectionName, callback) => {
          console.log(`ETSDB: Stopped watching collection ${collectionName}`);
        },
        
        getStats: async () => {
          const fileInfo = await fs.stat(config.path);
          return {
            type: 'file',
            path: config.path,
            size: fileInfo.size,
            // 其他统计信息...
          };
        },
        
        close: async () => {
          console.log(`ETSDB: File storage at ${config.path} closed`);
        }
      };
    } catch (error) {
      console.error('ETSDB: Failed to initialize file storage:', error);
      throw error;
    }
  },
  
  /**
   * 删除数据库文件
   * @param {string} path - 数据库路径
   * @returns {Promise<boolean>} 是否删除成功
   */
  async deleteDatabase(path) {
    try {
      await fs.unlink(path);
      console.log(`ETSDB: Database file ${path} deleted`);
      return true;
    } catch (error) {
      console.error(`ETSDB: Failed to delete database file ${path}:`, error);
      return false;
    }
  },
  
  /**
   * 检查文档是否匹配查询条件
   * @private
   * @param {Object} doc - 文档
   * @param {Object} query - 查询条件
   * @returns {boolean} 是否匹配
   */
  _matchesQuery(doc, query) {
    if (!query || typeof query !== 'object') {
      return true;
    }
    
    for (const [field, conditions] of Object.entries(query)) {
      const docValue = doc[field];
      
      if (typeof conditions === 'object' && conditions !== null) {
        // 处理操作符（如 $gte, $lte 等）
        for (const [operator, value] of Object.entries(conditions)) {
          switch (operator) {
            case '$eq':
              if (docValue !== value) return false;
              break;
            case '$ne':
              if (docValue === value) return false;
              break;
            case '$gt':
              if (!(docValue > value)) return false;
              break;
            case '$gte':
              if (!(docValue >= value)) return false;
              break;
            case '$lt':
              if (!(docValue < value)) return false;
              break;
            case '$lte':
              if (!(docValue <= value)) return false;
              break;
            case '$in':
              if (!Array.isArray(value) || !value.includes(docValue)) return false;
              break;
            case '$nin':
              if (!Array.isArray(value) || value.includes(docValue)) return false;
              break;
            default:
              // 未知操作符，跳过
              break;
          }
        }
      } else {
        // 简单的相等比较
        if (docValue !== conditions) {
          return false;
        }
      }
    }
    
    return true;
  },
  
  /**
   * 应用更新操作
   * @private
   * @param {Object} doc - 原始文档
   * @param {Object} update - 更新操作
   * @returns {Object} 更新后的文档
   */
  _applyUpdate(doc, update) {
    const updatedDoc = { ...doc };
    
    for (const [operator, operations] of Object.entries(update)) {
      switch (operator) {
        case '$set':
          // 设置字段值
          for (const [field, value] of Object.entries(operations)) {
            updatedDoc[field] = value;
          }
          break;
        case '$unset':
          // 删除字段
          for (const field of Object.keys(operations)) {
            delete updatedDoc[field];
          }
          break;
        case '$inc':
          // 增加数字字段
          for (const [field, value] of Object.entries(operations)) {
            if (typeof updatedDoc[field] === 'number') {
              updatedDoc[field] += value;
            }
          }
          break;
        case '$push':
          // 向数组添加元素
          for (const [field, value] of Object.entries(operations)) {
            if (Array.isArray(updatedDoc[field])) {
              updatedDoc[field].push(value);
            }
          }
          break;
        default:
          // 未知操作符，跳过
          break;
      }
    }
    
    return updatedDoc;
  },
  
  /**
   * 通知监听器
   * @private
   * @param {Map} listeners - 监听器映射
   * @param {string} collectionName - 集合名称
   * @param {Object} change - 变更信息
   */
  _notifyListeners(listeners, collectionName, change) {
    if (listeners.has(collectionName)) {
      const collectionListeners = listeners.get(collectionName);
      for (const callback of collectionListeners) {
        try {
          callback(change);
        } catch (error) {
          console.error('ETSDB: Error in listener callback:', error);
        }
      }
    }
  }
};

export default Utils;